package cn.est.controller;

import cn.est.config.WxConfig;
import cn.est.constants.Constants;
import cn.est.dto.Result;
import cn.est.exceptions.RedisException;
import cn.est.exceptions.TokenProtectedException;
import cn.est.pojo.Users;
import cn.est.service.TokenService;
import cn.est.service.UsersService;
import cn.est.utils.HttpClientUtil;
import cn.est.utils.RedisUtil;
import cn.est.utils.ResultUtils;
import cn.est.vo.TokenVo;
import cn.est.vo.WxTokenVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import io.lettuce.core.RedisURI;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import jdk.nashorn.internal.objects.annotations.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName WxController
 * @Description TODO
 * @Author yaozhaobao
 * @Date 2021/4/7 11:25
 * @Version 1.0
 **/
@Api("wx")
@RestController
@RequestMapping("/api/user")
public class WxController {
    @Autowired
    WxConfig wxConfig;

    @Autowired
    TokenService tokenService;

    @Autowired
    UsersService usersService;


    @Autowired
    RedisUtil redisUtil;

    @ApiOperation(value = "wx登录请求",produces="application/json",notes ="wx登录请求")
    //1.跳转到二维码授权页面的接口
    @GetMapping("/wxlogin")
    public void redirectWx(HttpServletResponse response) throws IOException {
        StringBuffer url=new StringBuffer("https://open.weixin.qq.com/connect/qrconnect?appid=").
                append(wxConfig.getAppid())
                .append("&redirect_uri=")
                .append(URLEncoder.encode("http://localhost:8080/est/api/user/callback"))
                .append("&response_type=code&scope=snsapi_login&state=hellowx#wechat_redirect");
        System.out.println(url.toString());
        response.sendRedirect(url.toString());
    }


    //2.用户授权后，回调的接口---code
    @GetMapping("/callback")
    public Result callback(String code, String state){
        if(state==null||!state.equals("hellowx")){
            ResultUtils.returnFail("非法请求");
        }
        //临时票据
        System.out.println(code);
        StringBuffer stringBuffer=new StringBuffer("https://api.weixin.qq.com/sns/oauth2/access_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&secret=");
        stringBuffer.append(wxConfig.getAppsecret());
        stringBuffer.append("&code=");
        stringBuffer.append(code);
        stringBuffer.append("&grant_type=authorization_code");
        String response=HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject=JSONObject.parseObject(response);
        System.out.println(jsonObject.getString("access_token"));
        System.out.println(jsonObject.getString("openid"));

        //1.判断接口是否能正确调用获取accesstoken
        if(jsonObject.get("errorCode")!=null){
            //说明出错，调用接口出错
            ResultUtils.returnFail((String) jsonObject.get("errmsg"), (String) jsonObject.get("errorCode"));
        }

        //2.判断当前openId是否存在在数据中，若不存在则需要插入数据实现注册功能
        Map map = new HashMap<String,Object>();
        map.put("openId",(String) jsonObject.get("openid"));
        List<Users> userList=usersService.getUsersListByMap(map);
        Users user=null;
        if(userList==null||userList.size()==0){
            user =new Users();
            user.setOpenId((String) jsonObject.get("openid"));
            user.setIsAuthentication(0);
            user.setCreatdTime(new Date());
            user.setIsDelete(0);
            usersService.qdtxAddUsers(user);
        }else{
            user=userList.get(0);
        }

        //3.生成本站的token，保存用户的登录信息。
        TokenVo tokenVo=tokenService.genenrateToken(user);

        //4.保存token到redis中
        tokenService.saveToken(tokenVo.getToken(),user);

        //5.返回token
       WxTokenVo wxTokenVo =new WxTokenVo();
        wxTokenVo.setTokenVo(tokenVo);
        wxTokenVo.setAccessToken((String) jsonObject.get("access_token"));
        wxTokenVo.setRefreshToken((String) jsonObject.get("refresh_token"));
        wxTokenVo.setExpiresTime(jsonObject.get("expires_in").toString());
        wxTokenVo.setOpenId((String) jsonObject.get("openid"));
        redisUtil.set("wx:"+tokenVo.getToken(),wxTokenVo, Constants.Token.WX_VALID_TIME);
        return ResultUtils.returnDataSuccess(tokenVo);

    }


    @PostMapping("/info")
    public Result getUserInfo(@RequestParam String token) throws UnsupportedEncodingException {
            //1.首先查看redis中是否存在token
                if((Users)redisUtil.get(token)==null){
                    return  ResultUtils.returnFail("token无效","20004");
                }

            //2.根据token获取redis中AccessToken
                String accessToken=((WxTokenVo)redisUtil.get("wx:"+token)).getAccessToken();
                String openId=((WxTokenVo)redisUtil.get("wx:"+token)).getOpenId();

            //3.拼接url请求请求用户数据接口
                StringBuffer stringBuffer =new StringBuffer("https://api.weixin.qq.com/sns/userinfo?access_token=");
                stringBuffer.append(accessToken);
                stringBuffer.append("&openid=");
                stringBuffer.append(openId);
                 String response= HttpClientUtil.doGet(stringBuffer.toString());
                JSONObject jsonObject= JSONObject.parseObject(response);
              //4.判断返回响应数据是否正确 errCode
                 if(jsonObject.get("errcode")!=null){
                return ResultUtils.returnFail(jsonObject.get("errmsg").toString(),jsonObject.get("errcode").toString());
                  }

            //5.若数据库没有这个用户信息则放在数据库中
              Map map = new HashMap<String,Object>();
              map.put("openId",(String) jsonObject.get("openid"));
              List<Users> userList=usersService.getUsersListByMap(map);
              Users user=userList.get(0);
              if(user.getName()==null||user.getName().equals("")){
               String nickname=new String(jsonObject.get("nickname").toString().getBytes("ISO-8859-1"),"UTF-8");
                    user.setName(nickname);
                    user.setSex(Integer.parseInt(jsonObject.get("sex").toString()));
                    user.setFaceUrl(jsonObject.get("headimgurl").toString());
                    usersService.qdtxModifyUsers(user);
              }
            //6.返回用户信息
            return  ResultUtils.returnDataSuccess(user);
    }
    /**
     * accesstoken的置换
     * @param token
     * @return
     */
    @ApiOperation(value = "wx置换token",produces="application/json",notes ="wx置换token")
    @PostMapping(value = "/refresh")
    public Result refreshWechatToken(@RequestHeader String token){

        //1.查看token是否有效，token到了置换期，则先重新生成token
        TokenVo tokenVo=null;
        try {
         tokenVo = tokenService.refreshToken(token);
        } catch (RedisException e) {
            e.printStackTrace();
        } catch (TokenProtectedException e) {
            e.printStackTrace();
        }
        WxTokenVo wxTokenVo= (WxTokenVo) redisUtil.get("wx:"+token);
        //2.置换accessToken
        StringBuffer stringBuffer=new StringBuffer("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&grant_type=");
        stringBuffer.append("refresh_token");
        stringBuffer.append("&refresh_token=");
        stringBuffer.append(wxTokenVo.getRefreshToken());
        String response=HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject = JSON.parseObject(response);
        if(jsonObject.get("error")!=null){
            return ResultUtils.returnFail(jsonObject.get("errmsg").toString(),jsonObject.get("error").toString());
        }
        wxTokenVo.setRefreshToken(jsonObject.get("refresh_token").toString());
        wxTokenVo.setAccessToken(jsonObject.get("access_token").toString());
        redisUtil.expire("wx:"+token,30);
        redisUtil.set("wx:"+tokenVo.getToken(),wxTokenVo, Constants.Token.WX_VALID_TIME);
        return ResultUtils.returnDataSuccess(tokenVo);
    }












}
